home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PROGRAMR / OLE2BOOK.ZIP / CHAP11.ZIP / CHAP11 / POLYLINE / DLLPOLY.CPP next >
C/C++ Source or Header  |  1993-06-13  |  9KB  |  381 lines

  1. /*
  2.  * DLLPOLY.CPP
  3.  * Modifications for Chapter 11 (CLSID Only)
  4.  *
  5.  * Polyline component object used in Schmoo that supports a custom
  6.  * interface IPolyline.  Contains DLL entry code and the component
  7.  * object exports DllGetClassObject and DllCanUnloadNow and the
  8.  * class factory object.
  9.  *
  10.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  11.  *
  12.  * Kraig Brockschmidt, Software Design Engineer
  13.  * Microsoft Systems Developer Relations
  14.  *
  15.  * Internet  :  kraigb@microsoft.com
  16.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  17.  */
  18.  
  19.  
  20. #define INITGUIDS
  21. #include "polyline.h"
  22.  
  23.  
  24. //Count number of objects and number of locks.
  25. ULONG       g_cObj=0;
  26. ULONG       g_cLock=0;
  27.  
  28. //DLL Instance handle
  29. HINSTANCE   hgInst;
  30.  
  31.  
  32. /*
  33.  * LibMain
  34.  *
  35.  * Purpose:
  36.  *  DLL-specific entry point called from LibEntry.
  37.  *
  38.  * Parameters:
  39.  *  hInst           HINSTANCE instance of the DLL.
  40.  *  wDataSeg        WORD segment selector of the DLL's data segment.
  41.  *  wHeapSize       WORD byte count of the heap.
  42.  *  lpCmdLine       LPSTR to command line used to start the module.
  43.  *
  44.  * Return Value:
  45.  *  HANDLE          Instance handle of the DLL.
  46.  *
  47.  */
  48.  
  49. HANDLE FAR PASCAL LibMain(HINSTANCE hInst, WORD wDataSeg
  50.     , WORD cbHeapSize, LPSTR lpCmdLine)
  51.     {
  52.     WNDCLASS    wc;
  53.  
  54.     if (0!=cbHeapSize)
  55.         UnlockData(0);
  56.  
  57.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  58.     wc.hInstance     = hInst;
  59.     wc.cbClsExtra    = 0;
  60.     wc.lpfnWndProc   = PolylineWndProc;
  61.     wc.cbWndExtra    = CBPOLYLINEWNDEXTRA;
  62.     wc.hIcon         = NULL;
  63.     wc.hCursor       = LoadCursor(NULL, IDC_CROSS);
  64.     wc.hbrBackground = NULL;
  65.     wc.lpszMenuName  = NULL;
  66.     wc.lpszClassName = SZCLASSPOLYLINE;
  67.  
  68.     if (!RegisterClass(&wc))
  69.         return 0;
  70.  
  71.     hgInst=hInst;
  72.     return hInst;
  73.     }
  74.  
  75.  
  76.  
  77.  
  78.  
  79. /*
  80.  * WEP
  81.  *
  82.  * Purpose:
  83.  *  Required DLL Exit function.  Does nothing.
  84.  *
  85.  * Parameters:
  86.  *  bSystemExit     BOOL indicating if the system is being shut
  87.  *                  down or the DLL has just been unloaded.
  88.  *
  89.  * Return Value:
  90.  *  void
  91.  *
  92.  */
  93.  
  94. void FAR PASCAL WEP(int bSystemExit)
  95.     {
  96.     return;
  97.     }
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104. /*
  105.  * DllGetClassObject
  106.  *
  107.  * Purpose:
  108.  *  Provides an IClassFactory for a given CLSID that this DLL is
  109.  *  registered to support.  This DLL is placed under the CLSID
  110.  *  in the registration database as the InProcServer.
  111.  *
  112.  * Parameters:
  113.  *  clsID           REFCLSID that identifies the class factory desired.
  114.  *                  Since this parameter is passed this DLL can handle
  115.  *                  any number of objects simply by returning different
  116.  *                  class factories here for different CLSIDs.
  117.  *
  118.  *  riid            REFIID specifying the interface the caller wants
  119.  *                  on the class object, usually IID_ClassFactory.
  120.  *
  121.  *  ppv             LPVOID FAR * in which to return the interface pointer.
  122.  *
  123.  * Return Value:
  124.  *  HRESULT         NOERROR on success, otherwise contains an error SCODE.
  125.  */
  126.  
  127. HRESULT __export FAR PASCAL DllGetClassObject(REFCLSID rclsid, REFIID riid
  128.     , LPVOID FAR *ppv)
  129.     {
  130.     if (!IsEqualCLSID(rclsid, CLSID_Polyline11))
  131.         return ResultFromScode(E_FAIL);
  132.  
  133.     //Check that we can provide the interface
  134.     if (!IsEqualIID(riid, IID_IUnknown) && !IsEqualIID(riid, IID_IClassFactory))
  135.         return ResultFromScode(E_NOINTERFACE);
  136.  
  137.     //Return our IClassFactory for Polyline objects
  138.     *ppv=(LPVOID)new CPolylineClassFactory;
  139.  
  140.     if (NULL==*ppv)
  141.         return ResultFromScode(E_OUTOFMEMORY);
  142.  
  143.     //Don't forget to AddRef the object through any interface we return
  144.     ((LPUNKNOWN)*ppv)->AddRef();
  145.  
  146.     return NOERROR;
  147.     }
  148.  
  149.  
  150.  
  151.  
  152.  
  153. /*
  154.  * DllCanUnloadNow
  155.  *
  156.  * Purpose:
  157.  *  Answers if the DLL can be freed, that is, if there are no
  158.  *  references to anything this DLL provides.
  159.  *
  160.  * Parameters:
  161.  *  None
  162.  *
  163.  * Return Value:
  164.  *  BOOL            TRUE if nothing is using us, FALSE otherwise.
  165.  */
  166.  
  167. STDAPI DllCanUnloadNow(void)
  168.     {
  169.     SCODE   sc;
  170.  
  171.     //Our answer is whether there are any object or locks
  172.     sc=(0L==g_cObj && 0==g_cLock) ? S_OK : S_FALSE;
  173.     return ResultFromScode(sc);
  174.     }
  175.  
  176.  
  177.  
  178.  
  179. /*
  180.  * ObjectDestroyed
  181.  *
  182.  * Purpose:
  183.  *  Function for the Polyline object to call when it gets destroyed.
  184.  *  Since we're in a DLL we only track the number of objects here
  185.  *  letting DllCanUnloadNow take care of the rest.
  186.  *
  187.  * Parameters:
  188.  *  None
  189.  *
  190.  * Return Value:
  191.  *  None
  192.  */
  193.  
  194. void FAR PASCAL ObjectDestroyed(void)
  195.     {
  196.     g_cObj--;
  197.     return;
  198.     }
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205. /*
  206.  * CPolylineClassFactory::CPolylineClassFactory
  207.  *
  208.  * Purpose:
  209.  *  Constructor for an object supporting an IClassFactory that
  210.  *  instantiates Polyline objects.
  211.  *
  212.  * Parameters:
  213.  *  None
  214.  */
  215.  
  216. CPolylineClassFactory::CPolylineClassFactory(void)
  217.     {
  218.     m_cRef =0L;
  219.     return;
  220.     }
  221.  
  222.  
  223.  
  224.  
  225.  
  226. /*
  227.  * CPolylineClassFactory::~CPolylineClassFactory
  228.  *
  229.  * Purpose:
  230.  *  Destructor for a CPolylineClassFactory object.  This will be
  231.  *  called when we ::Release the object to a zero reference count.
  232.  */
  233.  
  234. CPolylineClassFactory::~CPolylineClassFactory(void)
  235.     {
  236.     return;
  237.     }
  238.  
  239.  
  240.  
  241.  
  242.  
  243.  
  244. /*
  245.  * CPolylineClassFactory::QueryInterface
  246.  * CPolylineClassFactory::AddRef
  247.  * CPolylineClassFactory::Release
  248.  *
  249.  * Purpose:
  250.  *  IUnknown implementations for this object.
  251.  */
  252.  
  253. STDMETHODIMP CPolylineClassFactory::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  254.     {
  255.     *ppv=NULL;
  256.  
  257.     //Any interface on this object is the object pointer.
  258.     if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
  259.         *ppv=(LPVOID)this;
  260.  
  261.     /*
  262.      * If we actually assign an interface to ppv we need to AddRef it
  263.      * since we're returning a new pointer.
  264.      */
  265.     if (NULL!=*ppv)
  266.         {
  267.         ((LPUNKNOWN)*ppv)->AddRef();
  268.         return NOERROR;
  269.         }
  270.  
  271.     return ResultFromScode(E_NOINTERFACE);
  272.     }
  273.  
  274.  
  275. STDMETHODIMP_(ULONG) CPolylineClassFactory::AddRef(void)
  276.     {
  277.     return ++m_cRef;
  278.     }
  279.  
  280.  
  281. STDMETHODIMP_(ULONG) CPolylineClassFactory::Release(void)
  282.     {
  283.     ULONG           cRefT;
  284.  
  285.     cRefT=--m_cRef;
  286.  
  287.     if (0L==m_cRef)
  288.         delete this;
  289.  
  290.     return cRefT;
  291.     }
  292.  
  293.  
  294.  
  295.  
  296.  
  297.  
  298.  
  299. /*
  300.  * CPolylineClassFactory::CreateInstance
  301.  *
  302.  * Purpose:
  303.  *  Instantiates a Polyline object that supports the IPolyline
  304.  *  and IUnknown interfaces.  If the caller asks for a different
  305.  *  interface than these two then we fail.
  306.  *
  307.  * Parameters:
  308.  *  punkOuter       LPUNKNOWN to the controlling IUnknown if we are
  309.  *                  being used in an aggregation.
  310.  *  riid            REFIID identifying the interface the caller desires
  311.  *                  to have for the new object.
  312.  *  ppvObj          LPVOID FAR * in which to store the desired interface
  313.  *                  pointer for the new object.
  314.  *
  315.  * Return Value:
  316.  *  HRESULT         NOERROR if successful, otherwise contains E_NOINTERFACE
  317.  *                  if we cannot support the requested interface.
  318.  */
  319.  
  320. STDMETHODIMP CPolylineClassFactory::CreateInstance(LPUNKNOWN punkOuter
  321.     , REFIID riid, LPVOID FAR *ppvObj)
  322.     {
  323.     LPCPolyline         pObj;
  324.     HRESULT             hr;
  325.  
  326.     *ppvObj=NULL;
  327.     hr=ResultFromScode(E_OUTOFMEMORY);
  328.  
  329.     //Verify that if there is a controlling unknown it's asking for IUnknown
  330.     if (NULL!=punkOuter && !IsEqualIID(riid, IID_IUnknown))
  331.         return ResultFromScode(E_NOINTERFACE);
  332.  
  333.     //Create the object.  This also creates a window.
  334.     pObj=new CPolyline(punkOuter, ObjectDestroyed, hgInst);
  335.  
  336.     if (NULL==pObj)
  337.         return hr;
  338.  
  339.     if (pObj->FInit())
  340.         hr=pObj->QueryInterface(riid, ppvObj);
  341.  
  342.     //Kill the object if initial creation or FInit failed.
  343.     if (FAILED(hr))
  344.         delete pObj;
  345.     else
  346.         g_cObj++;
  347.  
  348.     return hr;
  349.     }
  350.  
  351.  
  352.  
  353.  
  354.  
  355.  
  356. /*
  357.  * CPolylineClassFactory::LockServer
  358.  *
  359.  * Purpose:
  360.  *  Increments or decrements the lock count of the DLL.  If the lock
  361.  *  count goes to zero and there are no objects, the DLL is allowed
  362.  *  to unload.  See DllCanUnloadNow.
  363.  *
  364.  * Parameters:
  365.  *  f